"""
字符串处理工具类，提供正则表达式查找、关键字查找、替换、字符串处理等功能
"""

import re
import html
import urllib.parse
from typing import Union, List, Tuple, Optional, Pattern


class StringUtils:
    """
    字符串处理工具类，提供各种字符串操作功能
    """
    
    @staticmethod
    def regex_search(text: str, pattern: Union[str, Pattern], flags: int = 0) -> List[str]:
        """
        使用正则表达式查找字符串

        :param text: 要搜索的文本
        :param pattern: 正则表达式模式
        :param flags: 正则表达式标志
        :return: 匹配的字符串列表
        """
        compiled_pattern = re.compile(pattern, flags)
        return compiled_pattern.findall(text)
    
    @staticmethod
    def regex_search_with_position(text: str, pattern: Union[str, Pattern], flags: int = 0) -> List[Tuple[str, int, int]]:
        """
        使用正则表达式查找字符串并返回位置信息

        :param text: 要搜索的文本
        :param pattern: 正则表达式模式
        :param flags: 正则表达式标志
        :return: 包含(匹配字符串, 起始位置, 结束位置)的元组列表
        """
        compiled_pattern = re.compile(pattern, flags)
        matches = []
        for match in compiled_pattern.finditer(text):
            matches.append((match.group(), match.start(), match.end()))
        return matches
    
    @staticmethod
    def keyword_exists(text: str, keyword: str, case_sensitive: bool = True) -> bool:
        """
        检查关键字是否存在于文本中

        :param text: 要搜索的文本
        :param keyword: 关键字
        :param case_sensitive: 是否区分大小写
        :return: 关键字是否存在
        """
        if case_sensitive:
            return keyword in text
        else:
            return keyword.lower() in text.lower()
    
    @staticmethod
    def keyword_count(text: str, keyword: str, case_sensitive: bool = True) -> int:
        """
        统计关键字在文本中出现的次数

        :param text: 要搜索的文本
        :param keyword: 关键字
        :param case_sensitive: 是否区分大小写
        :return: 关键字出现次数
        """
        if case_sensitive:
            return text.count(keyword)
        else:
            return text.lower().count(keyword.lower())
    
    @staticmethod
    def keyword_positions(text: str, keyword: str, case_sensitive: bool = True) -> List[int]:
        """
        查找关键字在文本中出现的所有位置

        :param text: 要搜索的文本
        :param keyword: 关键字
        :param case_sensitive: 是否区分大小写
        :return: 关键字出现位置列表
        """
        positions = []
        search_text = text if case_sensitive else text.lower()
        search_keyword = keyword if case_sensitive else keyword.lower()
        
        start = 0
        while True:
            pos = search_text.find(search_keyword, start)
            if pos == -1:
                break
            positions.append(pos)
            start = pos + 1
        return positions
    
    @staticmethod
    def replace_keyword(text: str, old: str, new: str, count: int = -1, case_sensitive: bool = True) -> str:
        """
        替换文本中的关键字

        :param text: 原始文本
        :param old: 要替换的旧字符串
        :param new: 新字符串
        :param count: 替换次数，-1表示替换所有
        :param case_sensitive: 是否区分大小写
        :return: 替换后的文本
        """
        if case_sensitive:
            return text.replace(old, new, count)
        else:
            # 使用正则表达式进行不区分大小写的替换
            pattern = re.compile(re.escape(old), re.IGNORECASE)
            if count == -1:
                return pattern.sub(new, text)
            else:
                return pattern.sub(new, text, count=count)
    
    @staticmethod
    def replace_regex(text: str, pattern: Union[str, Pattern], replacement: str, count: int = 0, flags: int = 0) -> str:
        """
        使用正则表达式替换文本

        :param text: 原始文本
        :param pattern: 正则表达式模式
        :param replacement: 替换字符串
        :param count: 替换次数，0表示替换所有
        :param flags: 正则表达式标志
        :return: 替换后的文本
        """
        compiled_pattern = re.compile(pattern, flags)
        return compiled_pattern.sub(replacement, text, count=count)
    
    @staticmethod
    def encode_url(text: str, encoding: str = 'utf-8') -> str:
        """
        将字符串进行URL编码

        :param text: 要编码的文本
        :param encoding: 字符串编码
        :return: URL编码后的字符串
        """
        return urllib.parse.quote(text, encoding=encoding)
    
    @staticmethod
    def decode_url(encoded_text: str, encoding: str = 'utf-8') -> str:
        """
        将URL编码的字符串进行解码

        :param encoded_text: URL编码的文本
        :param encoding: 解码后的字符串编码
        :return: 解码后的字符串
        """
        return urllib.parse.unquote(encoded_text, encoding=encoding)
    
    @staticmethod
    def encode_html(text: str) -> str:
        """
        将字符串进行HTML实体编码

        :param text: 要编码的文本
        :return: HTML实体编码后的字符串
        """
        return html.escape(text)
    
    @staticmethod
    def decode_html(encoded_text: str) -> str:
        """
        将HTML实体编码的字符串进行解码

        :param encoded_text: HTML实体编码的文本
        :return: 解码后的字符串
        """
        return html.unescape(encoded_text)
    
    @staticmethod
    def reverse_string(text: str) -> str:
        """
        反转字符串

        :param text: 要反转的字符串
        :return: 反转后的字符串
        """
        return text[::-1]
    
    @staticmethod
    def capitalize_words(text: str) -> str:
        """
        将字符串中每个单词的首字母大写

        :param text: 要处理的字符串
        :return: 处理后的字符串
        """
        return text.title()
    
    @staticmethod
    def remove_whitespace(text: str) -> str:
        """
        移除字符串中的所有空白字符

        :param text: 要处理的字符串
        :return: 移除空白字符后的字符串
        """
        return re.sub(r'\s+', '', text)
    
    @staticmethod
    def remove_extra_whitespace(text: str) -> str:
        """
        移除字符串中多余的空白字符，只保留单个空格

        :param text: 要处理的字符串
        :return: 处理后的字符串
        """
        return re.sub(r'\s+', ' ', text).strip()
    
    @staticmethod
    def truncate(text: str, max_length: int, suffix: str = '...') -> str:
        """
        截断字符串

        :param text: 要截断的字符串
        :param max_length: 最大长度
        :param suffix: 截断后添加的后缀
        :return: 截断后的字符串
        """
        if len(text) <= max_length:
            return text
        else:
            return text[:max_length - len(suffix)] + suffix
    
    @staticmethod
    def is_empty_or_whitespace(text: str) -> bool:
        """
        检查字符串是否为空或只包含空白字符

        :param text: 要检查的字符串
        :return: 是否为空或只包含空白字符
        """
        return not text or text.isspace()
    
    @staticmethod
    def split_lines(text: str, remove_empty: bool = True) -> List[str]:
        """
        将字符串按行分割

        :param text: 要分割的字符串
        :param remove_empty: 是否移除空行
        :return: 行列表
        """
        lines = text.splitlines()
        if remove_empty:
            lines = [line for line in lines if line.strip()]
        return lines
    
    @staticmethod
    def join_lines(lines: List[str], separator: str = '\n') -> str:
        """
        将行列表合并为字符串

        :param lines: 行列表
        :param separator: 行分隔符
        :return: 合并后的字符串
        """
        return separator.join(lines)
    
    @staticmethod
    def extract_numbers(text: str) -> List[str]:
        """
        从字符串中提取所有数字

        :param text: 要处理的字符串
        :return: 数字字符串列表
        """
        return re.findall(r'\d+', text)
    
    @staticmethod
    def extract_emails(text: str) -> List[str]:
        """
        从字符串中提取所有邮箱地址

        :param text: 要处理的字符串
        :return: 邮箱地址列表
        """
        pattern = r'\b[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Z|a-z]{2,}\b'
        return re.findall(pattern, text)
    
    @staticmethod
    def extract_urls(text: str) -> List[str]:
        """
        从字符串中提取所有URL

        :param text: 要处理的字符串
        :return: URL列表
        """
        pattern = r'http[s]?://(?:[a-zA-Z]|[0-9]|[$-_@.&+]|[!*\\(\\),]|(?:%[0-9a-fA-F][0-9a-fA-F]))+'
        return re.findall(pattern, text)
    
    @staticmethod
    def mask_sensitive(text: str, pattern: Union[str, Pattern], mask_char: str = '*') -> str:
        """
        遮蔽敏感信息

        :param text: 要处理的字符串
        :param pattern: 敏感信息的正则表达式模式
        :param mask_char: 遮蔽字符
        :return: 遮蔽后的字符串
        """
        def mask_match(match):
            return mask_char * len(match.group())
        
        compiled_pattern = re.compile(pattern)
        return compiled_pattern.sub(mask_match, text)
    
    @staticmethod
    def camel_to_snake(text: str) -> str:
        """
        驼峰命名转蛇形命名

        :param text: 驼峰命名的字符串
        :return: 蛇形命名的字符串
        """
        # 在大写字母前添加下划线，然后转为小写
        s1 = re.sub('(.)([A-Z][a-z]+)', r'\1_\2', text)
        return re.sub('([a-z0-9])([A-Z])', r'\1_\2', s1).lower()
    
    @staticmethod
    def snake_to_camel(text: str, capitalize_first: bool = False) -> str:
        """
        蛇形命名转驼峰命名

        :param text: 蛇形命名的字符串
        :param capitalize_first: 是否首字母大写
        :return: 驼峰命名的字符串
        """
        components = text.split('_')
        if capitalize_first:
            return ''.join(x.capitalize() for x in components)
        else:
            return components[0] + ''.join(x.capitalize() for x in components[1:])